package occupation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import loadsave.Memento;
import loadsave.loadsaveobject.Iterator;
import loadsave.loadsaveobject.LoadSaveCollectionComposite;
import loadsave.loadsaveobject.LoadSaveIndex;
import loadsave.loadsaveobject.LoadSaveMapComposite;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import loadsave.loadsaveobject.LoadSavePrimitive;
import model.ModelObject;
import skills.ActiveSkill;
import skills.Skill;
import stat.EntityStatList;
import stat.StatList;
import factory.SkillFactory;

public class Occupation extends ModelObject {
	
	private StatList initStatList;
	private ArrayList<ActiveSkill> activeSkillList;
	private HashMap<String,ActiveSkill> weaponSkillList;
	private ArrayList<Skill> upgradableSkillList;
	private ActiveSkill activeWeapon;
	private OccupationType type;
	
	public Occupation() {
		super(OccupationType.SMASHER.toString());
		initStatList        = new EntityStatList();
		activeSkillList     = new ArrayList<ActiveSkill>();
		weaponSkillList     = new HashMap<String, ActiveSkill>();
		upgradableSkillList = new ArrayList<Skill>();
		activeWeapon        = null;
		type 				= OccupationType.SMASHER;
	}
	
	public Occupation(StatList statList, OccupationType occupation, ArrayList<ActiveSkill> activeSkills,
			HashMap<String,ActiveSkill> weaponSkills, ArrayList<Skill> upSkills) {
		super(occupation.toString());
		initStatList = statList;
		activeSkillList = activeSkills;
		weaponSkillList = weaponSkills;
		upgradableSkillList = upSkills;
		type = occupation;
	}
	
	public ArrayList<ActiveSkill> getActiveSkillList() {
		return activeSkillList;
	}

	public HashMap<String, ActiveSkill> getWeaponSkillList() {
		return weaponSkillList;
	}

	public ArrayList<Skill> getUpgradableSkillList() {
		return upgradableSkillList;
	}

	public ActiveSkill getActiveWeapon() {
		return activeWeapon;
	}

	public OccupationType getOccupation() {
		return type;
	}
	
	public StatList getInitStatList() {	
		return initStatList;
	}
	
	public void setOccupation(OccupationType occupation) {
		type = occupation;
		this.notifyObservers();
	}
	
	public void setInitStatList(StatList statList) {
		initStatList = statList;
		this.notifyObservers();
	}
	public void setActiveWeapon(ActiveSkill active) {
		activeWeapon = active;
		this.notifyObservers();
	}
	public void setActiveWeapon(String activeSkillName) {
		activeWeapon = weaponSkillList.get(activeSkillName);
		this.notifyObservers();
	}

	public void addActiveSkill(ActiveSkill as) {
		activeSkillList.add(as);
		this.notifyObservers();
	}
	
	public void addUpgradableSkill(Skill s) {
		upgradableSkillList.add(s);
	}
	
	@Override
	public Memento getMemento() {
		return new Memento() {

			@Override
			public LoadSaveObject getState() {
				LoadSaveObject supersLSO = Occupation.super.getMemento().getState();
				Iterator<LoadSaveObject> i = supersLSO.getIterator();
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("", "Occupation");
				for (i.init(); i.hasNext(); i.next()) {
					toReturn.add(i.getCurrKey().getValue(), i.getCurrVal());
				}
				LoadSaveObject lso = initStatList.getMemento().getState();
				lso.setName("initStatList");
				toReturn.add(lso.getName(), lso);
				LoadSaveCollectionComposite list = new LoadSaveCollectionComposite("activeSkillList", "ArrayList", "ActiveSkill");
				int index = 0;
				for (ActiveSkill as : activeSkillList) {
					list.add(new LoadSaveIndex(index++), as.getMemento().getState());
				}
				toReturn.add(list.getName(), list);
				LoadSaveMapComposite map = new LoadSaveMapComposite("weaponSkillList", "HashMap", "String", "ActiveSkill");
				for (String as : weaponSkillList.keySet()) {
					map.add(new LoadSavePrimitive("","",as), weaponSkillList.get(as).getMemento().getState());
				}
				toReturn.add(map.getName(), map);
				list = new LoadSaveCollectionComposite("upgradableSkillList", "ArrayList", "Skill");
				index = 0;
				for (Skill as : upgradableSkillList) {
					list.add(new LoadSaveIndex(index++), as.getMemento().getState());
				}
				toReturn.add(list.getName(), list);
				lso = activeWeapon.getMemento().getState();
				lso.setName("activeWeapon");
				toReturn.add(lso.getName(), lso);
				toReturn.add("type", new LoadSavePrimitive("type", "OccupationType", type.toString()));
				return toReturn;
			}

			@Override
			public void restoreState(LoadSaveObject lso) {
				Occupation.super.getMemento().restoreState(lso);
				initStatList = new EntityStatList();
				initStatList.getMemento().restoreState(lso.get("initStatList"));
				activeSkillList = new ArrayList<ActiveSkill>();
				Iterator<LoadSaveObject> i = lso.get("activeSkillList").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					ActiveSkill toAdd = SkillFactory.createActiveSkill(i.getCurrVal());
					toAdd.getMemento().restoreState(i.getCurrVal());
					activeSkillList.add(toAdd);
				}
				weaponSkillList = new HashMap<String, ActiveSkill>();
				i = lso.get("weaponSkillList").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					ActiveSkill toAdd = SkillFactory.createActiveSkill(i.getCurrVal());
					toAdd.getMemento().restoreState(i.getCurrVal());
					weaponSkillList.put(toAdd.getName(), toAdd);
				}
				upgradableSkillList = new ArrayList<Skill>();
				i = lso.get("upgradableSkillList").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					Skill toAdd = SkillFactory.createSkill(i.getCurrVal());
					toAdd.getMemento().restoreState(i.getCurrVal());
					upgradableSkillList.add(toAdd);
				}
				activeWeapon = SkillFactory.createActiveSkill(lso.get("activeWeapon"));
				type = OccupationType.valueOf(lso.get("type").getValue());
			}
			
		};
	}
	
	@Override
	public Occupation clone() {
		Occupation toReturn = new Occupation(initStatList, type, new ArrayList<ActiveSkill>(),
				new HashMap<String, ActiveSkill>(), new ArrayList<Skill>());
		for (ActiveSkill as : activeSkillList)
			toReturn.activeSkillList.add(as.clone());
		for (String s : weaponSkillList.keySet())
			toReturn.weaponSkillList.put(s, weaponSkillList.get(s).clone());
		for (Skill as : upgradableSkillList)
			toReturn.upgradableSkillList.add(as.clone());
		return toReturn;
	}
}
